#pragma once
#include <memory>
#include <functional>
#include "fields.hpp"

// 通信抽象
namespace myrpc
{
    // 基础消息抽象
    class BaseMessage
    {
    public:
        using ptr = std::shared_ptr<BaseMessage>;
        virtual ~BaseMessage() {}
        virtual void setId(const std::string &id)
        {
            _id = id;
        }
        virtual std::string rid()
        {
            return _id;
        }
        virtual void setMType(MType mytype)
        {
            _mytype = mytype;
        }
        virtual MType mtype()
        {
            return _mytype;
        }

        // 需要完成的功能
        virtual std::string serialize() = 0;                  // 序列化
        virtual bool unserialize(const std::string &msg) = 0; // 反序列化
        // 反序列化之后，进行消息校验，看消息是否完整
        virtual bool check() = 0;                             // 对(反)序列化之后的结果进行检查
    private:
        MType _mytype;      // 消息类型
        std::string _id;
    };

    // 基础缓冲区抽象
    class BaseBuffer
    {
    public:
        using ptr = std::shared_ptr<BaseBuffer>;
        virtual size_t readableSize() = 0;                    // 返回当前缓冲区有多少数据
        virtual int32_t peekInt32() = 0;                      // 尝试从缓冲区读取4字节的数据(不删除)
        virtual void retrieveInt32() = 0;                     // 取出缓冲区的前4字节数据(从缓冲区中删除)
        virtual int32_t readInt32() = 0;                      // 直接读取并删除 == peekInt32() + retrieveInt32()
        virtual std::string retrieveAsString(size_t len) = 0; // 从缓冲区中取出指定长度的字符串
    };

    // 基础协议抽象
    class BaseProtocol
    {
    public:
        using ptr = std::shared_ptr<BaseProtocol>;
        // 接收
        virtual bool canProcessed(const BaseBuffer::ptr &buf) = 0; // 看缓冲区中的数据是否能够处理
        // 从缓冲区里取出消息并 让msg将消息带出，交给serialize进行处理
        virtual bool onMessage(const BaseBuffer::ptr &buf, BaseMessage::ptr &msg) = 0;
        // 发送
        // 对msg进行序列化，之后返回一个序列化之后的消息
        virtual std::string serialize(const BaseMessage::ptr &msg) = 0;
    };

    // 基础链接抽象
    class BaseConnection
    {
    public:
        using ptr = std::shared_ptr<BaseConnection>;
        virtual void send(const BaseMessage::ptr &msg) = 0; // 给我一条消息，我来发送
        virtual void shutdown() = 0;                        // 关闭连接
        virtual bool connected() = 0;                       // 检查链接是否正常
    };

    // 定义回调函数的类型
    // 连接建立成功
    using ConnectionCallback = std::function<void(const BaseConnection::ptr &)>;
    using CloseCallback = std::function<void(const BaseConnection::ptr &)>;
    using MessageCallback = std::function<void(const BaseConnection::ptr &, BaseMessage::ptr &)>;
    // 服务端 抽象
    class BaseServer
    {
    public:
        using ptr = std::shared_ptr<BaseServer>;
        virtual void setConnectionCallback(const ConnectionCallback &cb)
        {
            _cb_connection = cb;
        }
        virtual void setCloseCallback(const CloseCallback &cb)
        {
            _cb_close = cb;
        }
        virtual void setMessageCallback(const MessageCallback &cb)
        {
            _cb_message = cb;
        }
        virtual void start() = 0; // 启动服务器
    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };

    // 客户端的抽象
    class BaseClient
    {
    public:
        using ptr = std::shared_ptr<BaseClient>;
        // 连接建立成功时的回调函数
        virtual void setConnectionCallback(const ConnectionCallback &cb)
        {
            _cb_connection = cb;
        }
        // 连接关闭时的回调函数
        virtual void setCloseCallback(const CloseCallback &cb)
        {
            _cb_close = cb;
        }
        // 消息到来时的回调函数
        virtual void setMessageCallback(const MessageCallback &cb)
        {
            _cb_message = cb;
        }
        // 让派生类实现其功能
        virtual void connect() = 0;                         // 连接服务器
        virtual void shutdown() = 0;                        // 关闭连接
        virtual bool send(const BaseMessage::ptr &) = 0;    // 发送消息
        virtual BaseConnection::ptr connection() = 0;       // 获取连接对象
        virtual bool connected() = 0;                       // 判断连接是否正常

    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };
}